/*
* @Author: song
* @Description: 触控辅助
* @Date: 2024年04月16日 星期二 17:04:27
* @Modify:
*/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace SCore.UI
{
    public class UIFingerTrigger : MonoBehaviour
        , IPointerDownHandler
        , IPointerUpHandler
        , IDragHandler
        , IBeginDragHandler
        , IEndDragHandler
        , IScrollHandler
    {
        public Action<float> OnPinch;
        public Action<Vector2> OnDrag;
        public Action OnDragEnd;
        public Action<Vector2> OnClick;

        private class PointData
        {
            public int _pointId; //点 id
            public Vector2 _pointPosition; //点 位置
            public bool _down; //是否按下
        }

        private List<PointData> _pointData = new List<PointData>() //最多2指操作
        {
            new PointData(),
            new PointData(),
        };

        private float _pointDistance; //双点距离

        //拖拽状态
        private bool _drag = false;

        //双指操作
        private bool _pinch = false;


        private PointerEventData _pointerDragData;

        private int GetPointCount()
        {
            int count = 0;
            foreach (var point in _pointData)
            {
                if (point._down)
                {
                    count++;
                }
            }

            return count;
        }

        private void AddPoint(PointerEventData pointData)
        {
            for (int index = 0; index < 2; index++)
            {
                if (!_pointData[index]._down)
                {
                    _pointData[index]._pointId = pointData.pointerId;
                    _pointData[index]._pointPosition = pointData.position;
                    _pointData[index]._down = true;
                    break;
                }
            }
        }

        private void RemovePoint(PointerEventData pointData)
        {
            PointData removePoint = null;
            foreach (var point in _pointData)
            {
                if (point._pointId == pointData.pointerId)
                {
                    point._down = false;
                }
            }
        }

        public void UpdatePoint(PointerEventData pointData)
        {
            foreach (var point in _pointData)
            {
                if (point._pointId == pointData.pointerId)
                {
                    point._pointPosition = pointData.position;
                }
            }
        }

        void IBeginDragHandler.OnBeginDrag(PointerEventData eventData)
        {
            // XLog.Debug("OnBeginDrag");
            if (GetPointCount() == 1)
            {
                _drag = true;
            }
            else if (GetPointCount() == 2)
            {
                _drag = true; // 双手的时候 算 但是也在拖拽 为了屏蔽 双手释放的
                _pinch = true;
                _pointDistance = Vector2.Distance(_pointData[0]._pointPosition, _pointData[1]._pointPosition);
            }
        }

        void IDragHandler.OnDrag(PointerEventData eventData)
        {
            _pointerDragData = eventData;
            UpdatePoint(eventData);
        }

        void IEndDragHandler.OnEndDrag(PointerEventData eventData)
        {
            if (_pinch)
            {
                _pinch = false;
                OnPinch?.Invoke(0f);
            }
            else if (_drag)
            {
                _drag = false;
                OnDragEnd?.Invoke();
            }
        }

        void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
        {
            if (GetPointCount() < 2) //只考虑 2个手指
            {
                AddPoint(eventData);
            }
        }

        void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
        {
            if (!_drag && !_pinch && GetPointCount() == 1)
            {
                OnClick?.Invoke(eventData.position);
            }

            RemovePoint(eventData);
        }

        public void Update()
        {
#if !UNITY_EDITOR
            if (Input.touchCount == 0) //容错
            {
                foreach (var point in _pointData)
                {
                    point._down = false;
                }
            }
#endif
            if (_pointerDragData == null)
            {
                if (_pinch)
                {
                    OnPinch?.Invoke(0f);
                }
                else if (_drag)
                {
                    OnDrag?.Invoke(Vector2.zero);
                }

                return;
            }

            if (_pinch)
            {
                _pinch = true;
                float distance = Vector2.Distance(_pointData[0]._pointPosition, _pointData[1]._pointPosition);
                float opDistance = _pointDistance - distance;
                if (Mathf.Abs(opDistance) > 0.8f)
                {
                    OnPinch?.Invoke(opDistance);
                }
                else
                {
                    OnPinch?.Invoke(0);
                }

                _pointDistance = distance;
            }
            else if (_drag)
            {
                if (_pointerDragData.pointerId == _pointData[0]._pointId)
                {
                    OnDrag?.Invoke(_pointerDragData.delta);
                }
            }

            _pointerDragData = null;
        }

        void IScrollHandler.OnScroll(PointerEventData eventData)
        {
            OnPinch?.Invoke(eventData.scrollDelta.y * 100);
        }
    }
}